#pragma once
#include <string>
#include <unordered_map>
#include <vector>
#include <core/sync/lock.h>
#include "qbprotocol/include/SSQBModel.h"
#include "bondlib.h"

#define INVALID_CDC_VALUE	-1e6
struct sCDCPrice
{
	uint32_t		m_nEstDate;							//估值日期   
	char			m_sEstcleanprice[10];				//估值净价
	char			m_sEstPrice[10];					//估值收益率		中债估值
	char			m_sFrontEstcleanprice[10];				//估值净价
	char			m_sFrontEstPrice[10];					//估值收益率		中债估值
	char			m_sDuration[10];					//中债估值久期   
	sCDCPrice()
	{
		_InitializeString(m_sEstcleanprice);
		_InitializeString(m_sEstPrice);
		_InitializeString(m_sFrontEstcleanprice);
		_InitializeString(m_sFrontEstPrice);
		_InitializeString(m_sDuration);
		m_nEstDate = 0;
	}
};

class CBondCdcPriceUnit
{
public:
	CBondCdcPriceUnit();
	void Add(const int nPrcType, const xQBACDCPriceUnit_c& unit, bool bSpecial);
	bool GetEstimateElement(char* const estPrice, const int capacity, const int nOptType, const int nPrcType = 0, bool bYesterday = false) const;
	uint32_t GetEstimateDate() const;
	int	 GetSize() const;
	bool isSpecial() const;
private:
	// [内存优化][scofined.qi]
	// key为CBondCDCPriceInfo::kEstOptionType,固定整数值
	// 处于节省内存,以及缓存行友好的考虑,使用vector替换哈希表
	struct KeyValue{
		int			first;	// 取值为kEstOptionType
		sCDCPrice	second;	// 
	};
	class CDCPriceVec{
		std::vector<KeyValue>	m_values;
	public:
		using iterator = std::vector<KeyValue>::iterator;
		using const_iterator = std::vector<KeyValue>::const_iterator;
		int size()const{ return m_values.size(); }
		void clear(){ m_values.clear(); }
		const_iterator end()const{ return m_values.cend(); }
		const_iterator find(int optionType)const;
		iterator find(int optionType);
		void insert(int optionType, const sCDCPrice& price);
		sCDCPrice& operator[](int optionType);
	};
	typedef CDCPriceVec	Container;
	Container		m_mpBondCdc;
	bool			m_bSpecial;		//特殊估值
};

class S_BONDLIB_EXPORT CBondCDCPriceInfo
{
public:
	enum kEstOptionType
	{
		est_type_invalid = -2, //无效值
		est_type_combine = -1, //行权/到期， 外部提示辅助使用
		est_type_exercise,//行权中债估值
		est_type_expire,//到期中债估值
		est_type_null,
	};
	enum kPriceType
	{
		price_type_yield, //中债估值
		price_type_clean, //中债估值净价
		price_type_duration, //中债估值久期
	};
	static CBondCDCPriceInfo& instance();

	qb::base::CSLock&  GetMutex() { return m_mutex; }
	void	ClearAll();
	void	ClearNonSpecial();
	void	ClearSpecial();
	void	Add(const int nBondIndex, const xQBACDCPriceUnit_c& unit, bool bSpecial); //需要外部加锁
	bool isTodayDataValid(bool bSpec);

	//获取单券昨日中债估值 bSingle=true时 行权>到期，bSingle=false时 行权+到期
	std::string	GetCDCPriceYesterday(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType/* = CBondCDCPriceInfo::price_type_yield*/, bool bSingle/*=false*/);

	//获取单券今日中债估值 bSingle=true时 行权>到期，bSingle=false时 行权+到期
	std::string	GetCDCPriceToday(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType/* = CBondCDCPriceInfo::price_type_yield*/, bool bSingle/*=false*/);

	//获取单券最新中债估值 bSingle=true时 行权>到期，bSingle=false时 行权+到期
	std::string	GetCDCPriceLast(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType/* = CBondCDCPriceInfo::price_type_yield*/, bool bSingle/*=false*/);


	uint32_t	GetEstimateDate(const int nBondIndex);//获取估值相关元素\净价 久期等，优先取行权估值
    std::string	GetRelaEstimatePrice(const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType = 0/*CBondCDCPriceInfo::price_type_yield*/, const char* pRef = nullptr, bool bYesterday = false);//简单获取中债估值
    double	GetEstimatePriceGap(const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType = 0/*CBondCDCPriceInfo::price_type_yield*/, bool bReverse = true, const char* pRef = nullptr, const double dRef = INVALID_CDC_VALUE, bool bYesterday = false, bool bForceExercise = false);//默认中债-price

    void	GetExerciseAndMaturity(const bool bIsCdcAuthValid,const int nBondIndex,double &dExercise,double &dMaturity);

	//默认昨日中债-price, 
	double	GetYesterdayCDCPriceGap(const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType/*=CBondCDCPriceInfo::price_type_yield*/, bool bReverse/* = true*/, const char* pRef/* = nullptr*/, const double dRef/* = INVALID_CDC_VALUE*/, bool bForceExercise/* = false*/);

	//成交统计专用
	std::string GetCDCPriceYesterdayByOpt(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nOptTypeStart, const int nPrcType/* = CBondCDCPriceInfo::price_type_yield*/);

	static int GetCdcPrcType(const xQBACDCPriceUnit_c& unit);
	static bool IsPriceValid(const char* pPrc, bool bIsCdc = false);
	static std::string GetSplit();

private:
	CBondCDCPriceInfo();
	~CBondCDCPriceInfo() {}
private:
	std::unordered_map<int, CBondCdcPriceUnit> m_mpCdcContainer;
	qb::base::CSLock				m_mutex;
	unsigned int		m_updateDate = 0;
	unsigned int		m_updateDateSpec = 0;//特殊估值
};
